﻿using System;
using ArtMath.Data;
using ArtMath.Component.Point;
using ArtMath.Attribute;
using ArtMath.Core.Data;
using ArtMath.Resource;
using ArtMath.Component.Line;
using System.Drawing;
using ArtMath.Helper;
using ArtMath.Core.Helper;

namespace ArtMath.Component.Angle
{
    /// <summary>
    /// 约束角
    /// </summary>
    [Serializable]
    public class ConstrainedAngle : AngleBase
    {
        AngleStringX angle;
        public ConstrainedAngle(SketchPad pad, string name, string angle, bool addToList = true) : base(pad, name, ToolTypeName.ysj, addToList)
        {
            InPoints = new PointBase[2];
            StrAngle = new AngleStringX(Pad, angle);
            Angle = StrAngle.RadValue;
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("Angle")]
        public AngleStringX StrAngle
        {
            get { return angle; }
            set
            {
                if (angle is object)
                {
                    angle.ParametersValueChanging -= Angle_ParametersValueChanging;
                    angle.ParametersValueChanged -= Angle_ParametersValueChanged;
                    angle.ExpressionSetting -= Angle_ExpressionSetting;
                    angle.ExpressionSet -= Angle_ExpressionSet;
                }
                angle = value;
                if (angle is object)
                {
                    angle.ParametersValueChanging += Angle_ParametersValueChanging;
                    angle.ParametersValueChanged += Angle_ParametersValueChanged;
                    angle.ExpressionSetting += Angle_ExpressionSetting;
                    angle.ExpressionSet += Angle_ExpressionSet;
                }
            }
        }
        void Angle_ParametersValueChanged(DocStringX sender, ParametersValueChangedEventArgs e)
        {
            TerminalEdge.SourcePoint.TempMoveLock = true;
            if (Pad.MoveObject_DoMouseMove(TerminalEdge, PointD.Empty))
            {
                TerminalEdge.ComponentChanged(TerminalEdge);
            }
            else
            {

            }
            Pad.MoveObject_DoMouseUp(TerminalEdge);
            TerminalEdge.SourcePoint.TempMoveLock = false;
        }
        void Angle_ExpressionSet(StringX sender, ExpressionSetEventArgs e)
        {
            TerminalEdge.SourcePoint.TempMoveLock = true;
            if (Pad.MoveObject_DoMouseMove(TerminalEdge, PointD.Empty))
            {
                TerminalEdge.ComponentChanged(TerminalEdge);
            }
            else
            {
                Pad.ShowMessage(string.Format(Resources.Translate("FailModify"), OfTranslator("Angle")), MessageType.Error);
                StrAngle.SetExpression(e.OldExpression, false);
            }
            Pad.MoveObject_DoMouseUp(TerminalEdge);
            TerminalEdge.SourcePoint.TempMoveLock = false;
        }
        void Angle_ExpressionSetting(StringX sender)
        {
            TerminalEdge.SourcePoint.TempMoveLock = true;
            Pad.MoveObject_DoMouseDown(TerminalEdge);
            TerminalEdge.SourcePoint.TempMoveLock = false;
        }

        void Angle_ParametersValueChanging(DocStringX sender)
        {
            TerminalEdge.SourcePoint.TempMoveLock = true;
            Pad.MoveObject_DoMouseDown(TerminalEdge);
            TerminalEdge.SourcePoint.TempMoveLock = false;
        }
        public override void ComponentBuilding(Base component)
        {
            ShowStatus($"{Resources.Translate("Creating")}{Resources.ColonSeparate}{Name}");
            base.ComponentBuilding(component);
        }
        public override double NewAngle
        {
            get
            {
                return StrAngle.RadValue;
            }
        }
        public override bool CanDrawVirtual
        {
            get
            {
                return InitialEdge != null;
            }
        }
        public override void PaintVirtualObjects(Graphics gra)
        {
            if (CanDrawVirtual)
            {
                gra.DrawRay(Pad, Core.Helper.Painter.VirtualLinePen, InitialEdge.SourcePoint.Pxy, Pad.DegToPDeg((InitialEdge.DirectedAngle + Angle) * Core.Helper.Angle.RToD));
            }
        }
        public override void ComponentChanged(ShapeBase component)
        {
            if (component == InitialEdge)
            {
                TerminalEdge.ComponentChanged(TerminalEdge);
                return;
            }
            base.ComponentChanged(component);
        }
        public override void InternalPointMove(PointBase movePoint, Base sender = null)
        {
            TerminalEdge.ExternalObjectMove(movePoint, sender);
            base.InternalPointMove(movePoint, sender);
        }
        public override void CreateComponents()
        {
            TwoPointsRay tpr;
            if (InitialEdge == null)
            {
                InitialEdge = tpr = new TwoPointsRay(Pad, Resources.Translate(nameof(InitialEdge)), false) { SpareCoordinate_ = SpareCoordinate_, };
                tpr.CreateComponents(Resources.Translate("Vertex"));
            }
            else
            {
                tpr = InitialEdge as TwoPointsRay;
                tpr.CreateComponents(Resources.JoinLocalizedString("Direction", "Point"));
                Array.Copy(tpr.InPoints, InPoints, InPoints.Length);
                Pad.TrackObj = TerminalEdge = new AngleTerminalRay(Pad, Resources.Translate(nameof(TerminalEdge)), this)
                {
                    SourcePoint = Vertex,
                    DirectedAngle = InitialEdge.DirectedAngle + Angle,
                };
                TerminalEdge.CreateComponents();
                base.CreateComponents();
            }
        }
        public override object CopyAndPaste(SketchPad pad)
        {
            ConstrainedAngle ca = new ConstrainedAngle(pad, Utility.GetNextAvailableName(Name, pad.CheckObjectNameExist), StrAngle.DirectExpression, LayerItem != null);
            afterNewCopy(ca);
            return ca;
        }
    }
}
